﻿namespace ScrumLite.Data.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Transactions;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    /// <summary>
    /// Summary description for RequestsManagerFixture
    /// </summary>
    [TestClass]
    public class RequestStoreFixture
    {
        IRequestStore store;
        private static Guid projectId = new Guid("1C4F9968-8D5E-4d8a-9BD8-9A8DF1434B45");
        private static Guid aloneAreaId = new Guid("1C4F9968-8D5E-4d8a-9BD8-9A8DF1434B5A");
        private static Guid wa1Id = new Guid("1C4F9968-8D5E-4d8a-9BD8-9A8DF1434B5B");
        private static Guid wa2Id = new Guid("1C4F9968-8D5E-4d8a-9BD8-9A8DF1434B5C");
        private static Guid r3Id = new Guid("4567DF34-8D5E-4d8a-9BD8-9A8DF1434B5C");
        private static Guid r1Id = new Guid("4567DF34-8D5E-4d8a-9BD8-9A8DF1434FFF");
        private static Guid r2Id = new Guid("4567DF34-8D5E-4d8a-9BD8-9A8DF1434EEE");
        private static Guid r4Id = new Guid("4567DF34-8D5E-4d8a-9BD8-9A8DF1434FF4");
        private static DateTime dateDueOn = new DateTime(2008, 12, 31);

        [TestInitialize]
        public void Initialize()
        {
            store = new RequestStore();
        }

        [TestMethod()]
        public void ShouldGetRequestsByProjectOrderByStatusAndPriority()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();
                store.Add(new Request() { title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test", fk_project = projectId, en_status = 1 });
                IList<Request> requests = store.RetrieveRequests(projectId, null); 
                
                Assert.AreEqual(5, requests.Count);
                Assert.IsTrue(requests.First().en_status <= requests.Last().en_status);
            }
        }

        [TestMethod()]
        public void ShouldGetRequestsByProjectAndWorkAreaOrderByStatusAndPriority()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                Guid workAreaId = Guid.NewGuid();
                string workAreaName = "TestWorkArea";
                int moniker = store.RetrieveLastMoniker(MockHelpers.KnownProjectId)+1;
                store.Add(new Request() { title = "test", notes = "test", moniker = moniker, createdOn = DateTime.Now, requestor = "test", fk_project = MockHelpers.KnownProjectId, en_status = 1 });
                store.SaveWorkArea(new WorkArea() { fk_project = MockHelpers.KnownProjectId, name = workAreaName, id = workAreaId });
                store.AssignWorkAreas(MockHelpers.KnownProjectId, moniker, new string[] {workAreaId.ToString()});

                IList<Request> requests = store.RetrieveRequests(MockHelpers.KnownProjectId, workAreaName);

                Assert.AreEqual(1, requests.Count);
            }
        }

        [TestMethod]
        public void ShouldSetPrioritiesGivenASetOfRequestIds()
        {
            Guid[] requestIds = new Guid[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };

            using (TransactionScope scope = new TransactionScope())
            {
                Request req1 = new Request() { id = requestIds[0], priority = 2, title = "test", notes = "test", moniker = 1000, createdOn = DateTime.Now, requestor = "test", fk_project = MockHelpers.KnownProjectId, en_status = 1 };
                Request req2 = new Request() { id = requestIds[1], priority = 3, title = "test", notes = "test", moniker = 1001, createdOn = DateTime.Now, requestor = "test", fk_project = MockHelpers.KnownProjectId, en_status = 1 };
                Request req3 = new Request() { id = requestIds[2], priority = 1, title = "test", notes = "test", moniker = 1002, createdOn = DateTime.Now, requestor = "test", fk_project = MockHelpers.KnownProjectId, en_status = 1 };

                store.Add(req1);
                store.Add(req2);
                store.Add(req3);

                store.UpdateRequestsPriority(requestIds);

                IList<Request> requests = store.RetrieveRequests(MockHelpers.KnownProjectId, null);
                
                Assert.AreEqual<byte>(1, requests.First( r => r.id == requestIds[0] ).priority.Value);
                Assert.AreEqual<byte>(2, requests.First(r => r.id == requestIds[1]).priority.Value);
                Assert.AreEqual<byte>(3, requests.First(r => r.id == requestIds[2]).priority.Value);
            }
        }

        [TestMethod]
        public void ShouldUpdateRequest()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                WorkArea workarea = new WorkArea { id = Guid.NewGuid(), fk_project = MockHelpers.KnownProjectId, name = "WorkArea 1" };
                store.SaveWorkArea(workarea);
                WorkArea workarea2 = new WorkArea { id = Guid.NewGuid(), fk_project = MockHelpers.KnownProjectId, name = "WorkArea 2" };
                store.SaveWorkArea(workarea2);

                Guid requestId = Guid.NewGuid();

                RequestWorkArea requestWA = new RequestWorkArea { id = Guid.NewGuid(), fk_request = requestId, fk_workarea = workarea.id };
                System.Data.Linq.EntitySet<RequestWorkArea> requestWASet = new System.Data.Linq.EntitySet<RequestWorkArea>();
                requestWASet.Add(requestWA);

                Request request = new Request() { id = requestId, priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test", fk_project = MockHelpers.KnownProjectId, en_status = 1, RequestWorkAreas = requestWASet };
                store.Add(request);

                request.title = "Updated Title";
                request.en_status = 2;
                request.notes = "Updated notes";
                request.priority = 4;
                request.requestor = "Updated requestor";
                request.weight = 20;
                request.dueOn = new DateTime(2008, 12, 31);
                requestWASet.Add(new RequestWorkArea { id = Guid.NewGuid(), fk_request = requestId, fk_workarea = workarea2.id });
                request.RequestWorkAreas = requestWASet;
                store.Update(request, true);

                Request actual = store.RetrieveRequest(request.id);
                WorkArea[] actualWorkAreas = store.RetrieveWorkAreas(actual.fk_project, actual.moniker);

                Assert.AreEqual(request.title, actual.title);
                Assert.AreEqual(request.en_status, actual.en_status);
                Assert.AreEqual(request.notes, actual.notes);
                Assert.AreEqual(request.priority, actual.priority);
                Assert.AreEqual(request.requestor, actual.requestor);
                Assert.AreEqual(request.weight, actual.weight);
                Assert.AreEqual(request.dueOn, actual.dueOn);
                Assert.AreEqual(requestWASet.Count, actualWorkAreas.Length);
            }
        }

        [TestMethod]
        public void ShouldUpdateRequestButNotTheWorkAreas()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                WorkArea workarea = new WorkArea { id = Guid.NewGuid(), fk_project = MockHelpers.KnownProjectId, name = "WorkArea 1" };
                store.SaveWorkArea(workarea);
                WorkArea workarea2 = new WorkArea { id = Guid.NewGuid(), fk_project = MockHelpers.KnownProjectId, name = "WorkArea 2" };
                store.SaveWorkArea(workarea2);

                Guid requestId = Guid.NewGuid();

                RequestWorkArea requestWA = new RequestWorkArea { id = Guid.NewGuid(), fk_request = requestId, fk_workarea = workarea.id };
                System.Data.Linq.EntitySet<RequestWorkArea> requestWASet = new System.Data.Linq.EntitySet<RequestWorkArea>();
                requestWASet.Add(requestWA);

                Request request = new Request() { id = requestId, priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test", fk_project = MockHelpers.KnownProjectId, en_status = 1, RequestWorkAreas = requestWASet };
                store.Add(request);

                request.title = "Updated Title";
                request.en_status = 2;
                request.notes = "Updated notes";
                request.priority = 4;
                request.requestor = "Updated requestor";
                request.weight = 20;
                request.dueOn = new DateTime(2008, 12, 31);
                requestWASet.Add(new RequestWorkArea { id = Guid.NewGuid(), fk_request = requestId, fk_workarea = workarea2.id });
                request.RequestWorkAreas = requestWASet;
                store.Update(request, false);

                Request actual = store.RetrieveRequest(request.id);
                WorkArea[] actualWorkAreas = store.RetrieveWorkAreas(actual.fk_project, actual.moniker);

                Assert.AreEqual(request.title, actual.title);
                Assert.AreEqual(request.en_status, actual.en_status);
                Assert.AreEqual(request.notes, actual.notes);
                Assert.AreEqual(request.priority, actual.priority);
                Assert.AreEqual(request.requestor, actual.requestor);
                Assert.AreEqual(request.weight, actual.weight);
                Assert.AreEqual(request.dueOn, actual.dueOn);
                Assert.AreNotEqual(requestWASet.Count, actualWorkAreas.Length);
                Assert.AreEqual(1, actualWorkAreas.Length);
            }
        }

        [TestMethod]
        public void ShouldAddRequest()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                WorkArea workarea = new WorkArea { id = Guid.NewGuid(), fk_project = MockHelpers.KnownProjectId, name = "WorkArea 1" };
                store.SaveWorkArea(workarea);

                Guid requestId = Guid.NewGuid();

                RequestWorkArea requestWA = new RequestWorkArea { id = Guid.NewGuid(), fk_request = requestId, fk_workarea = workarea.id };
                System.Data.Linq.EntitySet<RequestWorkArea> requestWASet = new System.Data.Linq.EntitySet<RequestWorkArea>();
                requestWASet.Add(requestWA);

                Request request = new Request() { id = requestId, priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test", fk_project = MockHelpers.KnownProjectId, en_status = 1, dueOn = new DateTime(2008,12,31), RequestWorkAreas = requestWASet };

                store.Add(request);

                Request actual = store.RetrieveRequest(request.id);
                WorkArea[] actualWorkAreas = store.RetrieveWorkAreas(actual.fk_project, actual.moniker);

                Assert.AreEqual(request.title, actual.title);
                Assert.AreEqual(request.en_status, actual.en_status);
                Assert.AreEqual(request.notes, actual.notes);
                Assert.AreEqual(request.priority, actual.priority);
                Assert.AreEqual(request.requestor, actual.requestor);
                Assert.AreEqual(request.weight, actual.weight);
                Assert.AreEqual(request.dueOn, actual.dueOn);
                Assert.AreEqual(requestWASet.Count, actualWorkAreas.Length);
            }
        }

        [TestMethod]
        public void ShouldSetCompletedOnWhenRequestStatusIsSetToComplete()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                Request request = new Request() { id = Guid.NewGuid(), priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test", fk_project = MockHelpers.KnownProjectId, en_status = 1 };
                store.Add(request);

                request.en_status = 4;
                store.Update(request, false);

                Request actual = store.RetrieveRequest(request.id);

                Assert.IsTrue(actual.completedOn.HasValue);
                Assert.AreEqual(DateTime.Now.Date, actual.completedOn.Value.Date);
            }
        }

        public void ShouldNotUpdateCompletedOnWhenAPreviousValueExist()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                DateTime originalCompletedOn = DateTime.Now.Subtract(TimeSpan.FromDays(2));
                Request request = new Request() { id = Guid.NewGuid(), priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test", fk_project = MockHelpers.KnownProjectId, en_status = 4, completedOn = originalCompletedOn };
                store.Add(request);

                store.Update(request, false);

                Request actual = store.RetrieveRequest(request.id);

                Assert.IsTrue(actual.completedOn.HasValue);
                Assert.AreEqual(originalCompletedOn, actual.completedOn.Value);
            }
        }

        [TestMethod]
        public void ShouldDeleteRequest()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                Request request = new Request() { id = Guid.NewGuid(), priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test", fk_project = MockHelpers.KnownProjectId, en_status = 1 };
                store.Add(request);

                store.Delete(request.id);

                Request actual = store.RetrieveRequest(request.id);

                Assert.IsNull(actual);
            }
        }

        [TestMethod]
        public void ShouldGroupWorkAreasByWeight()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();
                Dictionary<Guid, WorkAreaReport> wa = store.RetrieveWorkAreasGroupedByWeight(projectId);

                Assert.AreEqual(3, wa.Count);
                Assert.IsTrue(wa.ContainsKey(wa1Id));
                Assert.IsTrue(wa.ContainsKey(wa2Id));
                Assert.AreEqual(20 + 3, wa[wa1Id].TotalWeight);
                Assert.AreEqual(2, wa[wa2Id].TotalWeight);
                Assert.AreEqual("Site Admin Tool", wa[wa1Id].Name);
                Assert.AreEqual("Modularity", wa[wa2Id].Name);
            }
        }

        [TestMethod]
        public void ShouldGroupWorkAreasByWeightWithWorkAreasWithoutRequests()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();
                Dictionary<Guid, WorkAreaReport> wa = store.RetrieveWorkAreasGroupedByWeight(projectId);

                Assert.AreEqual(3, wa.Count);
                Assert.IsTrue(wa.ContainsKey(wa1Id));
                Assert.IsTrue(wa.ContainsKey(wa2Id));
                Assert.IsTrue(wa.ContainsKey(aloneAreaId));
                Assert.AreEqual(20 + 3, wa[wa1Id].TotalWeight);
                Assert.AreEqual(2, wa[wa2Id].TotalWeight);
                Assert.AreEqual("Site Admin Tool", wa[wa1Id].Name);
                Assert.AreEqual("Modularity", wa[wa2Id].Name);
                Assert.AreEqual("AloneArea", wa[aloneAreaId].Name);
            }
        }

        [TestMethod]
        public void ShouldSaveAWorkArea()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                Guid Id = Guid.NewGuid();
                WorkArea workArea = new WorkArea() { name = "Name", id = Id, fk_project = MockHelpers.KnownProjectId };
                store.SaveWorkArea(workArea);
                                                               
                WorkArea[] actual = store.RetrieveWorkAreas (MockHelpers.KnownProjectId);

                Assert.IsNotNull(actual);
                WorkArea wa = actual.FirstOrDefault(t => t.id == Id);
                Assert.IsNotNull(wa);
                Assert.AreEqual("Name",wa.name);
                Assert.AreEqual(MockHelpers.KnownProjectId, wa.fk_project);
            }
        }

        [TestMethod]
        public void ShouldReturnZeroWorkAreasIfNoWorkAreaCreatedForProject()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();
                Dictionary<Guid, WorkAreaReport> wa = store.RetrieveWorkAreasGroupedByWeight(Guid.NewGuid());

                Assert.AreEqual(0, wa.Count);
            }
        }

        [TestMethod]
        public void ShouldGetAllWorkAreasAvailableForAProject()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();
                IList<WorkArea> wa = store.RetrieveWorkAreas(projectId);

                Assert.AreEqual(3, wa.Count);
            }
        }

        [TestMethod]
        public void ShouldGetAllWorkAreasAssignedToARequestOfAProject()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();
                IList<WorkArea> wa = store.RetrieveWorkAreas(projectId, 1);

                Assert.AreEqual(1, wa.Count);
            }
        }

        [TestMethod]
        public void ShouldAssignWorkAreasToARequestWithAGivenListOfWorkAreaIds()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();
                List<string> workAreas = new List<string>();
                workAreas.Add(aloneAreaId.ToString());
                store.AssignWorkAreas(projectId, 200, workAreas.ToArray());

                using (ScrumLiteDataContext context = new ScrumLiteDataContext())
                {
                    Guid[] reqList = (from requests in context.RequestWorkAreas
                                      where requests.fk_workarea == aloneAreaId
                                      select requests.fk_request).ToArray();

                    Assert.IsNotNull(reqList);
                    Assert.AreEqual(1, reqList.Count());
                    Assert.AreEqual(r3Id, reqList.First());
                }
            }
        }

        [TestMethod]
        public void ShouldNotAssignWorkAreasToARequestWithANullListOfWorkAreaIds()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();
                store.AssignWorkAreas(projectId, 200, null);

                using (ScrumLiteDataContext context = new ScrumLiteDataContext())
                {
                    Guid[] reqList = (from requests in context.RequestWorkAreas
                                      where requests.fk_request == r3Id
                                      select requests.fk_request).ToArray();

                    Assert.AreEqual(0, reqList.Count());
                }
            }
        }

        [TestMethod]
        public void ShouldReturnWorkAreasDeliverableCount()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();
                Dictionary<Guid, WorkAreaReport> wa = store.RetrieveWorkAreasGroupedByWeight(projectId);

                Assert.AreEqual(3, wa.Count);
                Assert.IsTrue(wa.ContainsKey(wa1Id));
                Assert.IsTrue(wa.ContainsKey(wa2Id));
                Assert.IsTrue(wa.ContainsKey(aloneAreaId));
                Assert.AreEqual("Site Admin Tool", wa[wa1Id].Name);
                Assert.AreEqual("Modularity", wa[wa2Id].Name);
                Assert.AreEqual("AloneArea", wa[aloneAreaId].Name);
                Assert.AreEqual(0, wa[wa2Id].DeliverableCount);
                Assert.AreEqual(2, wa[wa1Id].DeliverableCount);
                Assert.AreEqual(0, wa[aloneAreaId].DeliverableCount);
            }
        }

        [TestMethod]
        public void ShouldReturnWorkAreasRequestCount()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();
                Dictionary<Guid, WorkAreaReport> wa = store.RetrieveWorkAreasGroupedByWeight(projectId);

                Assert.AreEqual(3, wa.Count);
                Assert.IsTrue(wa.ContainsKey(wa1Id));
                Assert.IsTrue(wa.ContainsKey(wa2Id));
                Assert.IsTrue(wa.ContainsKey(aloneAreaId));
                Assert.AreEqual("Site Admin Tool", wa[wa1Id].Name);
                Assert.AreEqual("Modularity", wa[wa2Id].Name);
                Assert.AreEqual("AloneArea", wa[aloneAreaId].Name);
                Assert.AreEqual(1, wa[wa2Id].RequestCount);
                Assert.AreEqual(2, wa[wa1Id].RequestCount);
                Assert.AreEqual(0, wa[aloneAreaId].RequestCount);
            }
        }

        [TestMethod]
        public void ShouldReturnSingleStatusWorkAreaRequestsCount()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                Guid projectid = Guid.NewGuid();
                Guid workAreaId = Guid.NewGuid();
                CreateSingleWorkAreaSingleStatusRequests(projectid, workAreaId);

                Dictionary<WorkArea,Dictionary<byte?,int>> result;
                result = store.RetrieveRequestsByStatusByWorkArea(projectid);

                Assert.IsNotNull(result);
                Assert.AreEqual(1, result.Count);
                Assert.AreEqual(1, result.Count(w => w.Key.id == workAreaId));
                Dictionary<byte?, int> oneWorkArea = result.Single(w => w.Key.id == workAreaId).Value;
                Assert.AreEqual(1, oneWorkArea.Count);
                Assert.IsTrue(oneWorkArea.ContainsKey(1));
                Assert.AreEqual(2, oneWorkArea[1]);
            }
        }

        [TestMethod]
        public void ShouldReturnMultipleStatusWorkAreaRequestsCount()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                Guid projectId = Guid.NewGuid();
                Guid workAreaId1 = Guid.NewGuid();
                Guid workAreaId2 = Guid.NewGuid();

                CreateMultipleWorkAreaSingleStatusRequests(projectId, workAreaId1);
                CreateSingleWorkAreaSingleStatusRequests(projectId, workAreaId2);

                Dictionary<WorkArea, Dictionary<byte?, int>> result;
                result = store.RetrieveRequestsByStatusByWorkArea(projectId);

                Assert.IsNotNull(result);
                Assert.AreEqual(2, result.Count);
                Assert.AreEqual(1, result.Count(w => w.Key.id == workAreaId1));
                Assert.AreEqual(1, result.Count(w => w.Key.id == workAreaId2));
                Dictionary<byte?, int> oneWorkArea = result.Single(w => w.Key.id == workAreaId1).Value;
                Dictionary<byte?, int> twoWorkArea = result.Single(w => w.Key.id == workAreaId2).Value;
                Assert.AreEqual(3, oneWorkArea.Count);
                Assert.AreEqual(1, twoWorkArea.Count);
                Assert.IsTrue(oneWorkArea.ContainsKey(1));
                Assert.IsTrue(oneWorkArea.ContainsKey(2));
                Assert.IsTrue(oneWorkArea.ContainsKey(3));
                Assert.IsTrue(twoWorkArea.ContainsKey(1));
                Assert.AreEqual(2, oneWorkArea[1]);
                Assert.AreEqual(1, oneWorkArea[2]);
                Assert.AreEqual(1, oneWorkArea[3]);
                Assert.AreEqual(2, twoWorkArea[1]);
            }
        }

        [TestMethod]
        public void ShouldReturnMultipleStatusRequestsCount()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                Guid projectId = Guid.NewGuid();
                Guid workAreaId1 = Guid.NewGuid();
                Guid workAreaId2 = Guid.NewGuid();

                CreateMultipleWorkAreaSingleStatusRequests(projectId, workAreaId1);
                CreateSingleWorkAreaSingleStatusRequests(projectId, workAreaId2);

                Dictionary<byte?, int> result;
                result = store.RetrieveCountRequestsByStatus(projectId);

                Assert.IsNotNull(result);
                Assert.AreEqual(3, result.Count);
                Assert.IsTrue(result.ContainsKey(1));
                Assert.IsTrue(result.ContainsKey(2));
                Assert.IsTrue(result.ContainsKey(3));
                Assert.AreEqual(4, result[1]);
                Assert.AreEqual(1, result[2]);
                Assert.AreEqual(1, result[3]);
            }
        }

        [TestMethod]
        public void ShouldRetrieveCommittedRequest()
        {

            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();

                Request[] commitedRequests = this.store.RetrieveCommittedRequests(projectId);

                Assert.IsNotNull(commitedRequests);
                Assert.AreEqual(2, commitedRequests.Count());
                Assert.IsTrue(commitedRequests.Contains(commitedRequests.FirstOrDefault(r => r.id == r1Id)));
                Assert.IsTrue(commitedRequests.Contains(commitedRequests.FirstOrDefault(r => r.id == r3Id)));

            }
        }

        [TestMethod]
        public void ShouldRetrieveOpenedRequest()
        {

            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();

                Request[] openedRequests = this.store.RetrieveOpenedRequests(projectId);

                Assert.IsNotNull(openedRequests);
                Assert.AreEqual(3, openedRequests.Count());
                Assert.IsTrue(openedRequests.Contains(openedRequests.FirstOrDefault(r => r.id == r1Id)));
                Assert.IsTrue(openedRequests.Contains(openedRequests.FirstOrDefault(r => r.id == r2Id)));
                Assert.IsTrue(openedRequests.Contains(openedRequests.FirstOrDefault(r => r.id == r4Id)));

            }
        }

        [TestMethod]
        public void ShouldRetrieveCompletedRequest()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();

                Request[] completedRequests = this.store.RetrieveCompletedRequests(projectId);

                Assert.IsNotNull(completedRequests);
                Assert.AreEqual(1, completedRequests.Count());
                Assert.IsTrue(completedRequests.Contains(completedRequests.FirstOrDefault(r => r.id == r3Id)));
            }
        }

        [TestMethod]
        public void ShouldRetrieveRequest()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();

                Request actual = store.RetrieveRequest(projectId.ToString() , 1);

                Assert.IsNotNull(actual);
                Assert.AreEqual(1, actual.moniker);
                Assert.AreEqual(projectId, actual.fk_project);
                Assert.AreEqual(dateDueOn, actual.dueOn);
            }
        }

        [TestMethod]
        public void ShouldRetrieveLastOrder()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();

                int actual = store.RetrieveLastOrder(projectId);

                Assert.AreEqual(5, actual);
            }
        }

        [TestMethod]
        public void ShouldCleanCommittedRequestByStatus()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                using (ScrumLiteDataContext context = new ScrumLiteDataContext())
                {
                    CreateFakeRequestWorkAreas();

                    List<Request> previous = (from r in context.Requests
                                              where r.committed == true &&
                                              r.fk_project == projectId
                                              select r).ToList();

                    Assert.IsNotNull(previous);
                    Assert.AreEqual(2, previous.Count);
                    Assert.IsNotNull(previous.FirstOrDefault(req => req.id == r1Id));

                    store.CleanCommittedRequestByStatus(projectId, new byte[] { 3, 4, 5 });

                    Request[] actual = (from r in context.Requests
                                        where r.committed == true &&
                                        r.fk_project == projectId
                                        select r).ToArray();


                    Assert.IsNotNull(actual);
                    Assert.AreEqual(1, actual.Count());
                    Assert.IsNotNull(actual.FirstOrDefault(req => req.id == r1Id));
                }
            }
        }

        [TestMethod]
        public void ShouldRetrieveRequestStatusList()
        {

            using (TransactionScope scope = new TransactionScope())
            {
                CreateFakeRequestWorkAreas();

                RequestStatus[] statusList = this.store.RetrieveRequestStatusList();

                Assert.IsNotNull(statusList);
                Assert.AreEqual(5, statusList.Count());
                Assert.AreEqual("Taken", statusList[0].value.Trim());
                Assert.AreEqual("Waiting", statusList[1].value.Trim());
                Assert.AreEqual("Blocked", statusList[2].value.Trim());
                Assert.AreEqual("Completed", statusList[3].value.Trim());
                Assert.AreEqual("Postponed", statusList[4].value.Trim());
            }
        }

        private static void CreateMultipleWorkAreaSingleStatusRequests(Guid projectId, Guid workAreaId)
        {
            CreateSingleWorkAreaSingleStatusRequests(projectId, workAreaId);
            using (ScrumLiteDataContext context = new ScrumLiteDataContext())
            {
                Request r1 = new Request { id = Guid.NewGuid(), en_status = 2, fk_project = projectId, weight = 20, priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test" };
                Request r2 = new Request { id = Guid.NewGuid(), en_status = 3, fk_project = projectId, weight = 20, priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test" };

                RequestWorkArea rwa1 = new RequestWorkArea() { id = Guid.NewGuid(), fk_request = r1.id, fk_workarea = workAreaId };
                RequestWorkArea rwa2 = new RequestWorkArea() { id = Guid.NewGuid(), fk_request = r2.id, fk_workarea = workAreaId };

                context.Requests.InsertOnSubmit(r1);
                context.Requests.InsertOnSubmit(r2);
                context.RequestWorkAreas.InsertOnSubmit(rwa1);
                context.RequestWorkAreas.InsertOnSubmit(rwa2);

                context.SubmitChanges();
            }
        }

        private static void CreateSingleWorkAreaSingleStatusRequests(Guid projectId, Guid workAreaId)
        {
            using (ScrumLiteDataContext context = new ScrumLiteDataContext())
            {
                if (context.Projects.Count(p => p.id == projectId) == 0)
                {
                    Project p1 = new Project { id = projectId, name = "mock project", startsOn = DateTime.Now, uri_repository = string.Empty };
                    context.Projects.InsertOnSubmit(p1);
                }
                Request r1 = new Request { id = Guid.NewGuid(), en_status = 1, fk_project = projectId, weight = 20, priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test" };
                Request r2 = new Request { id = Guid.NewGuid(), en_status = 1, fk_project = projectId, weight = 20, priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test" };
                WorkArea wa1 = new WorkArea() { id = workAreaId, fk_project = projectId, name = "Site Admin Tool" };

                RequestWorkArea rwa1 = new RequestWorkArea() { id = Guid.NewGuid(), fk_request = r1.id, fk_workarea = wa1.id };
                RequestWorkArea rwa2 = new RequestWorkArea() { id = Guid.NewGuid(), fk_request = r2.id, fk_workarea = wa1.id };

                context.WorkAreas.InsertOnSubmit(wa1);
                context.Requests.InsertOnSubmit(r1);
                context.Requests.InsertOnSubmit(r2);
                context.RequestWorkAreas.InsertOnSubmit(rwa1);
                context.RequestWorkAreas.InsertOnSubmit(rwa2);

                context.SubmitChanges();
            }
        }

        private static void CreateFakeRequestWorkAreas()
        {
            using (ScrumLiteDataContext context = new ScrumLiteDataContext())
            {
                Project project = new Project() { endsOn = DateTime.Today, id = projectId, name = "FakeProject", security_group = "", startsOn = DateTime.Today, uri_repository = "", user_ownedBy = "" };
                context.Projects.InsertOnSubmit(project);

                Request r1 = new Request() { id = r1Id, weight = 20, priority = 2, title = "test", notes = "test", moniker = 1, createdOn = DateTime.Now, requestor = "test", fk_project = projectId, en_status = 1, committed = true, dueOn = dateDueOn};
                WorkArea wa1 = new WorkArea() { id = wa1Id, fk_project = projectId, name = "Site Admin Tool" };
                RequestWorkArea rwa1 = new RequestWorkArea()
                {
                    id = Guid.NewGuid(),
                    fk_request = r1.id,
                    fk_workarea = wa1.id
                };

                Deliverable d1 =new Deliverable() { fileName = "", id = Guid.NewGuid(), moniker = 1, pk_project = projectId, releasedOn = DateTime.Now, uri_repository ="" };
                DeliverableWorkArea dwa1 = new DeliverableWorkArea() { id = Guid.NewGuid(), pk_workarea = wa1.id, pk_deliverable = d1.id };

                Deliverable d2 = new Deliverable() { fileName = "", id = Guid.NewGuid(), moniker = 1, pk_project = projectId, releasedOn = DateTime.Now, uri_repository = "" };
                DeliverableWorkArea dwa2 = new DeliverableWorkArea() { id = Guid.NewGuid(), pk_workarea = wa1.id, pk_deliverable = d2.id };

                context.WorkAreas.InsertOnSubmit(wa1);
                context.Requests.InsertOnSubmit(r1);
                context.RequestWorkAreas.InsertOnSubmit(rwa1);
                context.Deliverables.InsertOnSubmit(d1);
                context.DeliverableWorkAreas.InsertOnSubmit(dwa1);
                context.Deliverables.InsertOnSubmit(d2);
                context.DeliverableWorkAreas.InsertOnSubmit(dwa2);

                Request r2 = new Request() { id = r2Id, weight = 3, priority = 2, title = "test", notes = "test", moniker = 2, createdOn = DateTime.Now, requestor = "test", fk_project = projectId, en_status = 2, committed = false, dueOn = dateDueOn };
                RequestWorkArea rwa2 = new RequestWorkArea()
                {
                    id = Guid.NewGuid(),
                    fk_request = r2.id,
                    fk_workarea = wa1.id
                };
                context.Requests.InsertOnSubmit(r2);
                context.RequestWorkAreas.InsertOnSubmit(rwa2);

                Request r3 = new Request() { id = r3Id, weight = 10, priority = 2, title = "test", notes = "test", moniker = 200, order=5, createdOn = DateTime.Now, requestor = "test", fk_project = projectId, en_status = 4, committed = true, completedOn = DateTime.Today, dueOn = dateDueOn };
                context.Requests.InsertOnSubmit(r3);

                Request r4 = new Request() { id = r4Id, weight = 2, priority = 2, title = "test", notes = "test", moniker = 3, createdOn = DateTime.Now, requestor = "test", fk_project = projectId, en_status = 3, committed = false, dueOn = dateDueOn };
                WorkArea wa4 = new WorkArea() { id = wa2Id, fk_project = projectId, name = "Modularity" };
                RequestWorkArea rwa4 = new RequestWorkArea()
                {
                    id = Guid.NewGuid(),
                    fk_request = r4.id,
                    fk_workarea = wa4.id
                };
                context.Requests.InsertOnSubmit(r4);
                context.WorkAreas.InsertOnSubmit(wa4);
                context.RequestWorkAreas.InsertOnSubmit(rwa4);

                WorkArea wa5 = new WorkArea() { id = aloneAreaId, fk_project = projectId, name = "AloneArea" };
                context.WorkAreas.InsertOnSubmit(wa5);

                context.SubmitChanges();
            }
        }
    }
}
